import cn.backflow.admin.common.pagination.PageRequest;
import cn.backflow.lib.util.StringUtil;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.InvalidDataAccessApiUsageException;

import java.lang.reflect.Array;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;


/**
 * Ognl工具类，主要是为了在ognl表达式访问静态方法时可以减少长长的类名称编写
 * Ognl访问静态方法的表达式为: @class@method(args) 如:
 * <p>
 * <pre>
 * 	&lt;if test="@Ognl@isNotEmpty(userId)">
 *     and user_id = #{userId}
 * &lt;/if>
 * </pre>
 */
public class Ognl {

    public static void main(String[] args) throws Exception {

        System.out.println(StringUtil.md5("taeyeon", "taeyeon"));

        SimpleDateFormat format = new SimpleDateFormat("yyyy-M-d");
        Date date = format.parse("2009-1-2");
        System.out.println(date);

    }
    /**
     * 可以用于判断String,Map,Collection,Array是否为空
     *
     * @param o 目标对象
     */
    public static boolean isEmpty(Object o) throws IllegalArgumentException {
        if (o == null) return true;

        if (o instanceof String) {
            if (((String) o).length() == 0) {
                return true;
            }
        } else if (o instanceof Collection) {
            if (((Collection<?>) o).isEmpty()) {
                return true;
            }
        } else if (o.getClass().isArray()) {
            if (Array.getLength(o) == 0) {
                return true;
            }
        } else if (o instanceof Map) {
            if (((Map<?, ?>) o).isEmpty()) {
                return true;
            }
        } else
            return false;
        return false;
    }

    /**
     * 可以用于判断 Map,Collection,String,Array是否不为空
     */
    public static boolean isNotEmpty(Object o) {
        return !isEmpty(o);
    }

    public static boolean isNotBlank(Object o) {
        return !isBlank(o);
    }

    public static boolean isNumber(Object o) {
        if (o == null) return false;
        if (o instanceof Number) return true;
        if (o instanceof String) {
            String str = (String) o;
            if (str.length() == 0) return false;
            if (str.trim().length() == 0) return false;
            try {
                Double.parseDouble(str);
                return true;
            } catch (NumberFormatException e) {
                return false;
            }
        }
        return false;
    }

    public static boolean isBlank(Object o) {
        return o == null || o instanceof String && isBlank((String) o);
    }

    public static boolean isBlank(String str) {
        if (str == null || str.length() == 0) return true;
        for (int i = 0; i < str.length(); i++) {
            if (!Character.isWhitespace(str.charAt(i))) {
                return false;
            }
        }
        return true;
    }

    /**
     * 用于验证那些列可以排序
     * ibatis示列使用
     * &lt;if test="@Ognl@checkOrderBy(orderBy,'username,password')">
     * ORDER BY ${orderBy}
     * &lt;/if>
     * <br>
     * <pre>
     * 返回示例:
     * 返回false相关验证:
     * checkOrderBy(null,"user,pwd")
     * checkOrderBy(" ","user,pwd")
     * checkOrderBy("user asc,pwd desc","user") pwd不能排序
     *
     * 返回true相关验证:
     * checkOrderBy("user asc,pwd desc",null)
     * checkOrderBy("user asc,pwd desc","")
     * checkOrderBy("user asc,pwd desc","user,pwd")
     * </pre>
     *
     * @param orderBy          需要验证的order by字符串
     * @param validSortColumns 可以排序的列
     * @throws DataAccessException
     */
    public static boolean checkOrderBy(String orderBy, String validSortColumns) throws DataAccessException {
        if (isBlank(orderBy))
            return false;
        if (orderBy.contains("'") || orderBy.contains("\\"))
            throw new IllegalArgumentException("orderBy:" + orderBy + " has SQL Injection risk");
        if (orderBy.length() > 50)
            throw new IllegalArgumentException("orderBy.length() <= 50 must be true");
        if (validSortColumns == null)
            return true;
        List<PageRequest.SortInfo> infos = PageRequest.SortInfo.parseSortColumns(orderBy);
        String[] passColumns = validSortColumns.split(",");
        for (PageRequest.SortInfo info : infos) {
            if (!isPass(passColumns, info)) {
                throw new InvalidDataAccessApiUsageException("orderBy:[" + orderBy + "] is invalid, only can orderBy:" + validSortColumns);
            }
        }
        return true;
    }

    private static boolean isPass(String[] passColumns, PageRequest.SortInfo info) {
        for (String column : passColumns) {
            if (column.equalsIgnoreCase(info.getColumn())) {
                return true;
            }
        }
        return false;
    }
}